package com.inetools.gwetons.client.cssStyleChangerBySelector;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;

import com.inetools.gwetons.client.JavaScriptObjectUtil;
import com.inetools.gwetons.client.cssStyleChangerBySelector.StyleChangerState.State;
import com.inetools.gwetons.shared.logging.LogUtil;
import com.inetools.gwetons.shared.logging.LogUtilAdapterTemplate;
import com.inetools.gwetons.shared.timer.TimerControllerFactoryUniInstanceHolder;
import com.inetools.gwetons.shared.timer.TimerControllerIntf;

public class StyleChangerTimerEventManager extends LogUtilAdapterTemplate {
	@Override
	protected String getNameForLogging() {
		return this.getClass().getName();
	}
	
	final CssStyleChangerDataUnit cssStyleChangerDataUnit;

	List<StyleChangerTimerEvent> styleChangerTimerEventList = new ArrayList<StyleChangerTimerEvent>();
	
	/*
	 * Pull all css style rules from cssStyleChangerDataUnitArray, and set initial value of 
	 * each css style rule when it already exists in any of supported-media-type style sheets.
	 * When any of css style rules from cssStyleChangerDataUnitArray does not exist in any of 
	 * supported-media-type style sheets, then it will be added to all supported-media-type 
	 * style sheets. <br />
	 * When any of supported-media-type style sheets does not exist, then a create style sheet and 
	 * add the css style rules from cssStyleChangerDataUnitArray to it. <br /> 
	 * Prerequisite: cssStyleChangerDataSet should have been slimed down by substantiateDataSet() before
	 */
	void prepDataUnitByStyleSelectorObjs( boolean reprep) {
		String methodName = "prepDataUnitByStyleSelectors";
		LogUtil logUtil = getLogUtil();
		logUtil.entering( methodName, new Object[]{ "reprep(=" + reprep + ")"});
		
		if ( reprep) {
			stopAllStyleChangerTimerEvents();
			styleChangerTimerEventList = new ArrayList<StyleChangerTimerEvent>();
		}
		if ( styleChangerTimerEventList.size() > 0) {
			logUtil.log( 
					Level.INFO, 
					"Already " + methodName + " method had been executed before."
					);
			logUtil.exiting( methodName);
			return;
		}
		
		List<DataUnitByStyleSelector> dataUnitByStyleSelectorList 
		= cssStyleChangerDataUnit.getDataUnitByStyleSelectorList();
		
		int dataUnitByStyleSelectorIndex = -1;
		Iterator<DataUnitByStyleSelector> dataUnitByStyleSelectorIterator 
		= dataUnitByStyleSelectorList.iterator();
		while( dataUnitByStyleSelectorIterator.hasNext()) {
			DataUnitByStyleSelector dataUnitByStyleSelector = dataUnitByStyleSelectorIterator.next();
			dataUnitByStyleSelectorIndex++;
			
			String selectorStr = dataUnitByStyleSelector.getSelector();
			String styleStr = dataUnitByStyleSelector.getStyle();
			String styleValueStr = "";
			Integer styleIntegerValue = null;
			
			if ( 
					dataUnitByStyleSelector.isInitValueNumeric() 
					&& dataUnitByStyleSelector.isEndValueNumeric()) 
			{ 
			// When initial and end values are numeric, 
			// set initValue (later add calculated difference unit to at each interval)
				
				styleIntegerValue = dataUnitByStyleSelector.getInitValue();
				
				if ( dataUnitByStyleSelector.isNumericColor()) {
					styleValueStr 
					= "#" + DataUnitByStyleSelector.getRGBColorHexStr( styleIntegerValue);
				}
				else {
					styleValueStr = styleValueStr 
							+ dataUnitByStyleSelector.getValuePrefix() 
							+ styleIntegerValue.toString() 
							+ dataUnitByStyleSelector.getValueUnit() 
							+ dataUnitByStyleSelector.getValueSuffix();
					styleValueStr 
					= JavaScriptObjectUtil.getURIComponentDecoded( styleValueStr);
						// Here it is not necessary considering the case that JavaScript's 
						// decodeURIComponent method (what is called in getURIComponentDecoded method) 
						// may throw the malformed URI sequence error, since substantiateDataSet 
						// method should have been already called as prerequisite. 
				}
				dataUnitByStyleSelector.setStyleValueStr( styleValueStr);
				
				if ( !cssStyleChangerDataUnit.isSequence() || ( dataUnitByStyleSelectorIndex < 1)) {
				/* If elements of selectorUnitArray property is not for sequential, then set 
				 * initValue property value of all elements to style sheet(s).
				 * No mater whether elements of selectorUnitArray property is not for sequential, 
				 * set initValue property value of first element to style sheet.
				 */
					if ( !DataUnitByStyleSelector
							.addCssRuleToStylesheet( selectorStr, styleStr, styleValueStr)) { 
					// When failed to update this style, remove this style to avoid later further processing 
						dataUnitByStyleSelectorIterator.remove();
						dataUnitByStyleSelectorIndex--;
						
						logUtil.log( 
								Level.WARNING, 
								"Removed DataUnitByStyleSelector instance for " + styleStr 
								+ " style of " + selectorStr + " selector because of failure " 
								+ "of intializing style by setting it to style sheet(s)."
								);
						continue; // while
					}
				}
				
				// Setup about initial value ------------------------------------------
				StyleChangerState styleChangerState = dataUnitByStyleSelector.styleChangerState;
				
				int stateIntValue = dataUnitByStyleSelector.getInitValue().intValue();
				styleChangerState.setStateValue( State.CurrentValue, stateIntValue); 
				if ( dataUnitByStyleSelector.isNumericColor()) {
					int[] rgbColorIntArray 
					= DataUnitByStyleSelector.getRGBColorElements( stateIntValue);
					styleChangerState.setStateValue( State.InitBlue, rgbColorIntArray[ 2]);
					styleChangerState.setStateValue( State.CurrentBlue, rgbColorIntArray[ 2]);
					styleChangerState.setStateValue( State.InitGreen, rgbColorIntArray[ 1]);
					styleChangerState.setStateValue( State.CurrentGreen, rgbColorIntArray[ 1]);
					styleChangerState.setStateValue( State.InitRed, rgbColorIntArray[ 0]);
					styleChangerState.setStateValue( State.CurrentRed, rgbColorIntArray[ 0]);
				}
				// --------------------------------------------------------------------
				
				// Setup about end value ----------------------------------------------
				stateIntValue = dataUnitByStyleSelector.getEndValue().intValue();
				styleChangerState.setStateValue( State.EndValue, stateIntValue); 
				if ( dataUnitByStyleSelector.isNumericColor()) {
					int[] rgbColorIntArray 
					= DataUnitByStyleSelector.getRGBColorElements( stateIntValue);
					styleChangerState.setStateValue( State.EndBlue, rgbColorIntArray[ 2]);
					styleChangerState.setStateValue( State.EndGreen, rgbColorIntArray[ 1]);
					styleChangerState.setStateValue( State.EndRed, rgbColorIntArray[ 0]);
				}
				// --------------------------------------------------------------------
				
				int period = dataUnitByStyleSelector.getPeriod().intValue();
				int interval = dataUnitByStyleSelector.getInterval().intValue();
				if ( period < interval) {
					logUtil.log( 
							Level.WARNING, 
							"Value(=" + interval + ") of " + JsDataPropertyIdentification.Interval.getJsPropertyName() 
							+ " property will be ignored to schedule timer even for " + styleStr 
							+ " style of " + selectorStr + " selector because it's bigger than value(=" 
							+ period + ") of " + JsDataPropertyIdentification.Period.getJsPropertyName()
							+ " propety."
							);
				}
				else { // period >= interval
					// Setup about unit of difference between initial value and end value -------------
					int intervalCount = 0;
						if ( interval <= 0) {
							intervalCount = 1;
						}
						else {
							intervalCount = period/interval;
						}
					stateIntValue 
					= (styleChangerState.getStateValue( State.EndValue).intValue() 
							- styleChangerState.getStateValue( State.CurrentValue).intValue())
							/intervalCount;
					styleChangerState.setStateValue( State.DiffUnit, stateIntValue);
					if ( dataUnitByStyleSelector.isNumericColor()) {
						int[] rgbColorIntArray 
						= DataUnitByStyleSelector.getRGBColorElements( stateIntValue);
						styleChangerState.setStateValue( State.BlueDiffUnit, rgbColorIntArray[ 2]);
						styleChangerState.setStateValue( State.GreenDiffUnit, rgbColorIntArray[ 1]);
						styleChangerState.setStateValue( State.RedDiffUnit, rgbColorIntArray[ 0]);
					}
					// --------------------------------------------------------------------------------
				}
				
				logUtil.log( 
						Level.FINE, 
						"Having set " + styleStr + " style of " + selectorStr + " selector " 
						+ "and initialized styleChangerState member field for it."
						);
			}
			else {
			// Either or both of initValue and endValue is not numeric
			// Set initial value (and later just set end value after specified period)  
				styleValueStr = dataUnitByStyleSelector.getInitValueStr();
					if ( ( styleValueStr != null) && !"".equals( styleValueStr)) {
						styleValueStr = styleValueStr 
								+ dataUnitByStyleSelector.getValuePrefix() 
								+ dataUnitByStyleSelector.getInitValueStr() 
								+ dataUnitByStyleSelector.getValueUnit() 
								+ dataUnitByStyleSelector.getValueSuffix();
						styleValueStr 
						= JavaScriptObjectUtil.getURIComponentDecoded( styleValueStr);
							// Here it is not necessary considering the case that JavaScript's 
							// decodeURIComponent method (what is called in getURIComponentDecoded method) 
							// may throw the malformed URI sequence error, since substantiateDataSet 
							// method should have been already called as prerequisite. 
					}
					
				dataUnitByStyleSelector.setStyleValueStr( styleValueStr);
				
				if ( styleValueStr != null) {
					if ( !cssStyleChangerDataUnit.isSequence() || ( dataUnitByStyleSelectorIndex < 1)) {
					/* If elements of selectorUnitArray property is not for sequential, then set 
					 * initValue property value of all elements of selectorUnitArray property to 
					 * style sheet(s).
					 * Even elements of selectorUnitArray property are for sequential, 
					 * set initValue property value of first element to style sheet.
					 */
						if ( !DataUnitByStyleSelector.addCssRuleToStylesheet( 
								selectorStr, styleStr, styleValueStr)) { 
						// When failed to update this style, remove this style to avoid further processing 
							dataUnitByStyleSelectorIterator.remove();
							dataUnitByStyleSelectorIndex--;
							
							logUtil.log( 
									Level.FINE, 
									"Removed DataUnitByStyleSelector instance for " + styleStr 
									+ " style of " + selectorStr + " selector because of failure " 
									+ "of intializing style by setting it to style sheet(s)."
									);
							continue; // while
						}
					}
					
				}
				
				logUtil.log( 
						Level.FINE, 
						"Having set " + styleStr + " style of " + selectorStr + " selector."
						);
			}
			
			
			StyleChangerTimerEvent styleChangerTimerEvent 
			= new StyleChangerTimerEvent( dataUnitByStyleSelector, this);
				styleChangerTimerEventList.add( styleChangerTimerEvent);
		} // while
		
		logUtil.exiting( methodName);
		return;
	}
	
	private static TimerControllerIntf timerController 
	= TimerControllerFactoryUniInstanceHolder.getTimerController();
		protected static TimerControllerIntf getTimerController() {
			return timerController;
		}
		protected static void setTimerController( TimerControllerIntf timerController) {
			StyleChangerTimerEventManager.timerController = timerController;
		}
	public StyleChangerTimerEventManager( CssStyleChangerDataUnit cssStyleChangerDataUnit) {
		this.cssStyleChangerDataUnit = cssStyleChangerDataUnit;
		prepDataUnitByStyleSelectorObjs( false);
	}
	
	boolean isSchedulingStarted = false;
		boolean isSchedulingStarted() {
			return isSchedulingStarted;
		}
		void setSchedulingStarted( boolean isSchedulingStarted) {
			this.isSchedulingStarted = isSchedulingStarted;
		}

	void beginStyleChangerTimerEvent() {
		String methodName = "beginStyleChangerTimerEvent";
		LogUtil logUtil = getLogUtil();
		logUtil.entering( methodName, null);

		if ( styleChangerTimerEventList.size() < 1) {
			logUtil.log( 
					Level.INFO, 
					"No StyleChangerTimerEvent instance has not been enlisted and prepared to start."
					);
			logUtil.exiting( methodName);
			return;
		}
		
		if ( isSchedulingStarted() && !isFinished()) {
			logUtil.log( 
					Level.INFO, 
					"Timer event has been already started before."
					);
			logUtil.exiting( methodName);
			return;
		}
		
		setSchedulingStarted( true);
		setFinished( false);
		
		Iterator<StyleChangerTimerEvent> styleChangerTimerEventIterator 
		= styleChangerTimerEventList.iterator();
		while( styleChangerTimerEventIterator.hasNext()) {
			StyleChangerTimerEvent styleChangerTimerEvent = styleChangerTimerEventIterator.next();
			
			int period = styleChangerTimerEvent.dataUnitByStyleSelector.getPeriod().intValue();
			int interval = styleChangerTimerEvent.dataUnitByStyleSelector.getInterval().intValue();
			if ( period < interval) {
				StyleChangerTimerEventManager
				.getTimerController().schedule( styleChangerTimerEvent, period);
			}
			else {
				StyleChangerTimerEventManager
				.getTimerController().scheduleRepeating( styleChangerTimerEvent, interval);
			}
			styleChangerTimerEvent.setFinished( false);
			
			if ( cssStyleChangerDataUnit.isSequence()) { // schedule only for first styleChangerTimerEvent
				break; // while
			}
		} // while
		
		logUtil.exiting( methodName);
	}
	
	/* Used for counting call to startNextStyleChangerTimerEvent method in order to 
	 * keep track of the number of StyleChangerTimerEvent instance what reached to 
	 * its end state. 
	 */
	int styleChangerTimerEventCounter = 0;
		int getStyleChangerTimerEventCounter() {
			return styleChangerTimerEventCounter;
		}
		void resetStyleChangerTimerEventCounter() {
			styleChangerTimerEventCounter = 0;
		}
		void increaseStyleChangerTimerEventCounter() {
			styleChangerTimerEventCounter++;
		}
		void decreaseStyleChangerTimerEventCounter() {
			String methodName = "decreaseStyleChangerTimerEventCounter";
			LogUtil logUtil = getLogUtil();
			logUtil.entering( methodName, null);
			
			if ( styleChangerTimerEventCounter == 0) {
				logUtil.log( 
						Level.WARNING,
						"Operation is aborted to avoid value of styleChangerTimerEventCounter member field " 
						+ "becomes less than 0."
						);
				logUtil.exiting( methodName);
				return;
			}
			styleChangerTimerEventCounter--;
			
			logUtil.exiting( methodName);
		}
	
	boolean remove( StyleChangerTimerEvent styleChangerTimerEvent) {
		String methodName = "startNextStyleChangerTimerEvent";
		LogUtil logUtil = getLogUtil();
		logUtil.entering( 
				methodName, 
				new Object[]{ 
						"styleChangerTimerEvent(= " + ((styleChangerTimerEvent == null) ? 
								"null" : styleChangerTimerEvent.toString()) + ")"
						}
				); 
		
		boolean removeResult = styleChangerTimerEventList.remove( styleChangerTimerEvent);
// TODO Should I remove styleChangerTimerEvent.dataUnitByStyleSelector from cssStyleChangerDataUnit.getDataUnitByStyleSelectorList() too?
			if ( removeResult) {
				decreaseStyleChangerTimerEventCounter();
				
				if ( !styleChangerTimerEvent.isFinished()) {
					styleChangerTimerEvent.setFinished( true);
				}
				
				logUtil.log( 
						Level.WARNING, 
						styleChangerTimerEvent.getClass().getName() + " instance for "
						+ styleChangerTimerEvent.dataUnitByStyleSelector.getStyle() + " style on " 
						+ styleChangerTimerEvent.dataUnitByStyleSelector.getSelector() + " selector " 
						+ "was removed from futher event scheduling and processing."
						);
// TODO Should I reset style in style sheets to initValue of styleChangerTimerEvent.dataUnitByStyleSelector?
			}
			else {
				logUtil.log( 
						Level.WARNING, 
						"Could not remove " + styleChangerTimerEvent.getClass().getName() + " instance for "
						+ styleChangerTimerEvent.dataUnitByStyleSelector.getStyle() + " style on " 
						+ styleChangerTimerEvent.dataUnitByStyleSelector.getSelector() + " selector."
						);
			}
		
		logUtil.exiting( methodName, removeResult);
		return removeResult;
	}
	
	/* This is called only from StyleChangerTimerEvent.fire method
	 */
	void startNextStyleChangerTimerEvent( StyleChangerTimerEvent instance, boolean remove) {
		String methodName = "startNextStyleChangerTimerEvent";
		LogUtil logUtil = getLogUtil();
		logUtil.entering( 
				methodName, 
				new Object[]{ 
						"instance(=" + ((instance == null) ? "null" : instance.toString()) + ")", 
						"remove(=" + remove + ")"
						}
				);
		
		if ( !isSchedulingStarted()) {
			logUtil.log( 
					Level.SEVERE, 
					"startStyleChangerTimerEvent method had to be executed before."
					);
			logUtil.exiting( methodName);
			return;
		}
		
		int styleChangerTimerEventIndex = styleChangerTimerEventList.indexOf( instance);
			if ( styleChangerTimerEventIndex < 0) {
				logUtil.log( 
						Level.SEVERE, 
						"Could not locate " + ((instance == null) ? "null" : instance.toString()) 
						+ " StyleChangerTimerEvent instance in styleChangerTimerEventList member field."
						);
				logUtil.exiting( methodName);
				return;
			}
		
		increaseStyleChangerTimerEventCounter();
			if ( getStyleChangerTimerEventCounter() == styleChangerTimerEventList.size()) {
				if ( !cssStyleChangerDataUnit.isRepeatable()) {
					setFinished( true);
				}
			}
		
		if ( !cssStyleChangerDataUnit.isSequence()) {
		// Wait until all StyleChangerTimerEvent instances finish, and restart all of them at same time once again 
			if ( remove) {
				remove( instance);
				if ( styleChangerTimerEventList.size() < 1) {
					setFinished( true);
					logUtil.exiting( methodName);
					return;
				}
			}
			
			if ( !cssStyleChangerDataUnit.isRepeatable()) {
				setFinished( true);
				logUtil.exiting( methodName);
				return;
			}
			if ( getStyleChangerTimerEventCounter() < styleChangerTimerEventList.size()) {
				logUtil.exiting( methodName);
				return;
			}
			
			// start all StyleChangerTimerEvent instances again -----------------------------------
			resetStyleChangerTimerEventCounter();
			
			Iterator<StyleChangerTimerEvent> styleChangerTimerEventIterator 
			= styleChangerTimerEventList.iterator();
			while( styleChangerTimerEventIterator.hasNext()) {
				StyleChangerTimerEvent styleChangerTimerEvent = styleChangerTimerEventIterator.next();
				
				if ( !styleChangerTimerEvent.isFinished()) {
					logUtil.log(
							Level.WARNING,
							"Cancelling StyleChangerTimerEvent instance for " 
							+ styleChangerTimerEvent.dataUnitByStyleSelector.getStyle() + " style of "
							+ styleChangerTimerEvent.dataUnitByStyleSelector.getSelector() + " selector "
							+ "since it is appeared as not finished though should have been at finished " 
							+ "state; this implies failure of tracking each StyleChangerTimerEvent instance"
							);
					StyleChangerTimerEventManager.getTimerController().cancel( styleChangerTimerEvent);
					styleChangerTimerEvent.setFinished( true);
				}
				
				if ( styleChangerTimerEvent.dataUnitByStyleSelector.getStyleValueStr() != null) {
					// Reset style sheets by initValue of each dataUnitByStyleSelector 
					boolean addCssRuleToStylesheetResult 
					= !DataUnitByStyleSelector.addCssRuleToStylesheet(
							styleChangerTimerEvent.dataUnitByStyleSelector.getSelector(), 
							styleChangerTimerEvent.dataUnitByStyleSelector.getStyle(), 
							styleChangerTimerEvent.dataUnitByStyleSelector.getStyleValueStr() 
							);
						if ( !addCssRuleToStylesheetResult) {
							remove( styleChangerTimerEvent);
							continue; // while
						}
				}
				
				int period = styleChangerTimerEvent.dataUnitByStyleSelector.getPeriod().intValue();
				int interval = styleChangerTimerEvent.dataUnitByStyleSelector.getInterval().intValue();
//TODO need to assure that timer event by these schedule method invocation does not occur until this while loop ends 
				if ( period < interval) {
					StyleChangerTimerEventManager
					.getTimerController().schedule( styleChangerTimerEvent, period);
				}
				else {
					StyleChangerTimerEventManager
					.getTimerController().scheduleRepeating( styleChangerTimerEvent, interval);
				}
				styleChangerTimerEvent.setFinished( false);
			} // while
			// ------------------------------------------------------------------------------------
		}
		else { // sequence property value is true
			boolean isPreEventInstanceAbandonned = remove;
			StyleChangerTimerEvent preStyleChangerTimerEvent = instance;
			StyleChangerTimerEvent styleChangerTimerEvent;
			do {
				styleChangerTimerEventIndex++;
				if ( styleChangerTimerEventIndex == styleChangerTimerEventList.size()) {
					if ( !cssStyleChangerDataUnit.isRepeatable()) {
						// Before giving up control, remove preStyleChangerTimerEvent when it's necessary
						if ( isPreEventInstanceAbandonned) {
							remove( preStyleChangerTimerEvent);
						}
						
						setFinished( true);
						logUtil.exiting( methodName);
						return;
					}
					
					// Back to top StyleChangerTimerEvent instance in list and schedule it
					styleChangerTimerEventIndex = 0;
				}
				

				styleChangerTimerEvent = styleChangerTimerEventList.get( styleChangerTimerEventIndex);
				if ( isPreEventInstanceAbandonned) {
					remove( preStyleChangerTimerEvent);
					
					if ( styleChangerTimerEventList.size() < 1) {
					// No StyleChangerTimerEvent instance left after removing preStyleChangerTimerEvent
						setFinished( true);
						logUtil.exiting( methodName);
						return;
					}
				}
				// Set initValue of styleChangerTimerEvent.dataUnitByStyleSelector to style sheets
				if ( styleChangerTimerEvent.dataUnitByStyleSelector.getStyleValueStr() == null) {
					isPreEventInstanceAbandonned = false;
				}
				else {
					isPreEventInstanceAbandonned 
					= !DataUnitByStyleSelector.addCssRuleToStylesheet(
							styleChangerTimerEvent.dataUnitByStyleSelector.getSelector(), 
							styleChangerTimerEvent.dataUnitByStyleSelector.getStyle(), 
							styleChangerTimerEvent.dataUnitByStyleSelector.getStyleValueStr() 
							);
					if ( isPreEventInstanceAbandonned) {
						preStyleChangerTimerEvent = styleChangerTimerEvent;
						increaseStyleChangerTimerEventCounter();
							// Increase styleChangerTimerEventCounter in advance to prepare decrease during removal 
					}
				}
			} while( isPreEventInstanceAbandonned);
			
			int period = styleChangerTimerEvent.dataUnitByStyleSelector.getPeriod().intValue();
			int interval = styleChangerTimerEvent.dataUnitByStyleSelector.getInterval().intValue();
			if ( period < interval) {
				StyleChangerTimerEventManager
				.getTimerController().schedule( styleChangerTimerEvent, period);
			}
			else {
				StyleChangerTimerEventManager
				.getTimerController().scheduleRepeating( styleChangerTimerEvent, interval);
			}
			styleChangerTimerEvent.setFinished( false);
		}
		
		logUtil.exiting( methodName);
	}
	
	boolean finished = false;
		public boolean isFinished() {
			return finished;
		}
		void setFinished( boolean finished) {
			this.finished = finished;
		}
	
	public void stopAllStyleChangerTimerEvents() {
		String methodName = "startNextStyleChangerTimerEvent";
		LogUtil logUtil = getLogUtil();
		logUtil.entering( methodName, null);
		
		setSchedulingStarted( false);
		setFinished( true);
		
		if ( styleChangerTimerEventList.size() < 1) {
			logUtil.exiting( methodName);
			return;
		}
		
		Iterator<StyleChangerTimerEvent> styleChangerTimerEventIterator 
		= styleChangerTimerEventList.iterator();
		while( styleChangerTimerEventIterator.hasNext()) {
			StyleChangerTimerEvent styleChangerTimerEvent = styleChangerTimerEventIterator.next();
			if ( !styleChangerTimerEvent.isFinished()) {
				StyleChangerTimerEventManager.getTimerController().cancel( styleChangerTimerEvent);
				styleChangerTimerEvent.setFinished( true);
			}
		} // while
		
		logUtil.exiting( methodName);
	}
}
